package dca.sistemascontrole.handler;

import dca.sistemascontrole.dao.GraphicDataManager;
import dca.sistemascontrole.domain.VariaveisAnalise;
import dca.sistemascontrole.driver.GerenciadorComunicacao;
import dca.sistemascontrole.malhadecontrole.Clock;
import dca.sistemascontrole.malhadecontrole.Controlador;
import dca.sistemascontrole.malhadecontrole.ControladorCascata;
import dca.sistemascontrole.malhadecontrole.MalhaAberta;
import dca.sistemascontrole.malhadecontrole.MalhaDeControle;
import dca.sistemascontrole.malhadecontrole.MalhaFechada;
import dca.sistemascontrole.util.ControleConstantes;
import dca.sistemascontrole.util.XMLManager;
import dca.sistemascontrole.view.GeradorAnalises;
import dca.sistemascontrole.view.MainFrame;
import dca.sistemascontrole.view.PanelAnalises;
import dca.sistemascontrole.view.configuracao.DialogConfigurarPortas;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.swing.JFileChooser;

/**
 *
 * @author Rafael
 */
public class HandlerMainFrame {

    private Clock clock;
    private MainFrame mainFrame;
    private Controlador controlador;
    private PanelAnalises pnlAnalises;
    private VariaveisAnalise variaveisAnalise;
    private MalhaDeControle malhaDeControle = new MalhaAberta();
    private GraphicDataManager graphicDataManager = new GraphicDataManager();
    private GerenciadorComunicacao gerenciadorComunicacao = new GerenciadorComunicacao();

    public HandlerMainFrame(MainFrame mainFrame, PanelAnalises panelAnalises) {
        clock = new Clock(this);
        this.mainFrame = mainFrame;
        this.pnlAnalises = panelAnalises;
    }

    public void setMalhaDeControle(MalhaDeControle malhaDeControle) {
        this.malhaDeControle = malhaDeControle;

        if ((malhaDeControle.getTipo() & MalhaDeControle.MALHA_FECHADA) == MalhaDeControle.MALHA_FECHADA) {
            variaveisAnalise = new VariaveisAnalise(((MalhaFechada) malhaDeControle).getSetpoint());
        } else {
            variaveisAnalise = null;
        }
    }

    public void setMalhaDeControle(int tipoControlador, float setPoint, float kp, float ki, float kd, float tw, float gama,
            boolean usarFiltroDerivativo, boolean usarFiltroAntiWindup) {
        if (MalhaDeControle.isMalhaFechada(tipoControlador)) {
            if (tipoControlador == malhaDeControle.getTipo()) {
                ((MalhaFechada) malhaDeControle).setKd(kd);
                ((MalhaFechada) malhaDeControle).setKi(ki);
                ((MalhaFechada) malhaDeControle).setKp(kp);
                ((MalhaFechada) malhaDeControle).setTw(tw);
                ((MalhaFechada) malhaDeControle).setGama(gama);
                ((MalhaFechada) malhaDeControle).setSetpoint(setPoint);
                ((MalhaFechada) malhaDeControle).setUsarFiltroAntiWindup(usarFiltroAntiWindup);
                ((MalhaFechada) malhaDeControle).setUsarFiltroDerivativo(usarFiltroDerivativo);
            } else {
                malhaDeControle = MalhaFechada.criarMalhaFechada(tipoControlador, setPoint, kp, ki, kd, usarFiltroDerivativo, usarFiltroAntiWindup);
                ((MalhaFechada) malhaDeControle).setTw(tw);
                ((MalhaFechada) malhaDeControle).setGama(gama);
            }

            variaveisAnalise = new VariaveisAnalise(setPoint);
        }
    }

    public void setMalhaDeControleCascata(int tipoControlador, float setPoint, float kpMestre, float kiMestre, float kdMestre,
            float kpEscravo, float kiEscravo, float kdEscravo, float tw, float gama, boolean usarFiltroDerivativo, 
            boolean usarFiltroAntiWindup) {
        
        if (MalhaDeControle.isMalhaCascata(tipoControlador)) {
            if (tipoControlador == MalhaDeControle.MALHA_CASCATA) {
                ((ControladorCascata) malhaDeControle).setKdMestre(kdMestre);
                ((ControladorCascata) malhaDeControle).setKiMestre(kiMestre);
                ((ControladorCascata) malhaDeControle).setKpMestre(kpMestre);
                ((ControladorCascata) malhaDeControle).setKdEscravo(kdEscravo);
                ((ControladorCascata) malhaDeControle).setKiEscravo(kiEscravo);
                ((ControladorCascata) malhaDeControle).setKpEscravo(kpEscravo);
                ((ControladorCascata) malhaDeControle).setTw(tw);
                ((ControladorCascata) malhaDeControle).setGama(gama);
                ((ControladorCascata) malhaDeControle).setSetpoint(setPoint);
                ((ControladorCascata) malhaDeControle).setUsarFiltroAntiWindup(usarFiltroAntiWindup);
                ((ControladorCascata) malhaDeControle).setUsarFiltroDerivativo(usarFiltroDerivativo);
            } else {
                MalhaFechada controladorMestre = MalhaFechada.criarMalhaFechada(tipoControlador, setPoint, 
                        kpMestre, kiMestre, kdMestre, usarFiltroDerivativo, usarFiltroAntiWindup);
                MalhaFechada controladorEscravo = MalhaFechada.criarMalhaFechada(tipoControlador, setPoint, 
                        kpEscravo, kiEscravo, kdEscravo, usarFiltroDerivativo, usarFiltroAntiWindup);
                
                malhaDeControle = new ControladorCascata(setPoint, controladorMestre, controladorEscravo);
                ((ControladorCascata) malhaDeControle).setTw(tw);
                ((ControladorCascata) malhaDeControle).setGama(gama);
            }

            variaveisAnalise = new VariaveisAnalise(setPoint);
        }
    }

    public void interromper() {
        malhaDeControle = new MalhaAberta();
    }

    public void showDialogoConfiguração() {
        DialogConfigurarPortas dialogoConfigurarPortas = new DialogConfigurarPortas(mainFrame, true, gerenciadorComunicacao);
        dialogoConfigurarPortas.setVisible(true);
    }

    public synchronized void setVariaveisNivel(double nivelTanqueSuperior, double nivelTanqueInferior, double setPoint, double erro, long t) {
        mainFrame.setVariaveisNivel(nivelTanqueSuperior, nivelTanqueInferior, setPoint, erro, t);

        graphicDataManager.addTanqueInferior(nivelTanqueInferior, t);
        graphicDataManager.addTanqueSuperior(nivelTanqueSuperior, t);
        graphicDataManager.addSetpoint(setPoint, t);
        graphicDataManager.addErro(erro, t);

        pnlAnalises.calcularAnalises(setPoint, nivelTanqueSuperior, nivelTanqueInferior);

        if (variaveisAnalise != null) {
            variaveisAnalise.addTanqueInferior(nivelTanqueInferior, t);
            variaveisAnalise.addTanqueSuperior(nivelTanqueSuperior, t);
        }
    }

    public synchronized void setVariaveisTensao(double uSaturado, double u, double ui, double up, double ud, long t) {
        mainFrame.setVariaveisTensao(uSaturado, u, ui, up, ud, t);

        graphicDataManager.addUSaturado(uSaturado, t);
        graphicDataManager.addU(u, t);
        graphicDataManager.addUi(ui, t);
        graphicDataManager.addUp(up, t);
        graphicDataManager.addUd(ud, t);
    }

    public void usarFiltroDerivativo(boolean usar) {
        if (malhaDeControle instanceof MalhaFechada) {
            ((MalhaFechada) malhaDeControle).setUsarFiltroDerivativo(usar);
        }
    }

    public void usarFiltroAntiWindup(boolean usar) {
        if (malhaDeControle instanceof MalhaFechada) {
            ((MalhaFechada) malhaDeControle).setUsarFiltroDerivativo(usar);
        }
    }

    public void gerarAnalise() {
        if (variaveisAnalise != null) {
            GeradorAnalises geradorAnalises = new GeradorAnalises(mainFrame, false, variaveisAnalise);
            geradorAnalises.gerarAnalises();
            geradorAnalises.mostrarAnalise();
        }
    }

    public void saveGraphicData() throws FileNotFoundException, IOException {
        JFileChooser fileChooser = new JFileChooser(new File(ControleConstantes.FILE_CONFIGURACAO));
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        int option = fileChooser.showOpenDialog(mainFrame);

        if (option == JFileChooser.APPROVE_OPTION) {
            String absolutePath = fileChooser.getSelectedFile().getAbsolutePath();

            XMLManager.writeObject(graphicDataManager, absolutePath + "." + ControleConstantes.FILE_IDENTIFICADOR_DADOS);
        }
    }

    public void iniciarClock() {
        clock.start();
    }

    public void runControlador(long t) {
        if (controlador == null || controlador.isDone()) {
            controlador = new Controlador(malhaDeControle, this, gerenciadorComunicacao, t);
            controlador.execute();
        }
    }

    public void clear() {
        graphicDataManager.clear();
    }
}
